﻿using System.Threading;
using System.Threading.Tasks;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using zijian666.Core;
using zijian666.DI;


namespace UnitTests;

[TestClass]
public class 回调测试
{
    [TestMethod]
    public void Test()
    {
        int a = 0;
        int b = 0;
        int c = 0;
        int d = 0;

        ErrorReporter.OutChannels = OutChannels.Console;
        var builder = Host.CreateDefaultBuilder().AddComponents();

        Assert.AreEqual(0, a);
        Assert.AreEqual(0, b);
        Assert.AreEqual(0, c);
        Assert.AreEqual(0, d);

        _ = builder.ConfigureServices((context, services) =>
        {
            a++;
            _ = services.OnConfigure(_ => ++a);
            _ = services.OnConfigure(_ => Task.FromResult(++b));
            _ = services.OnStop(_ => ++c);
            _ = services.OnStop(_ => Task.FromResult(++d));
        });

        Assert.AreEqual(0, a);
        Assert.AreEqual(0, b);
        Assert.AreEqual(0, c);
        Assert.AreEqual(0, d);

        using (var host = builder.Build())
        {
            Assert.AreEqual(1, a);
            Assert.AreEqual(0, b);
            Assert.AreEqual(0, c);
            Assert.AreEqual(0, d);

            var task = host.RunAsync();
            Thread.Sleep(1000);
            Assert.AreEqual(2, a);
            Assert.AreEqual(1, b);
            Assert.AreEqual(0, c);
            Assert.AreEqual(0, d);
            host.StopAsync().Wait();
            task.Wait();
        }


        Assert.AreEqual(2, a);
        Assert.AreEqual(1, b);
        Assert.AreEqual(1, c);
        Assert.AreEqual(1, d);
    }


    [TestMethod]
    public void Test2()
    {
        var startup = new Startup();
        Assert.AreEqual(0, startup.A);
        Assert.AreEqual(0, startup.B);
        Assert.AreEqual(0, startup.C);
        var builder = Host.CreateDefaultBuilder().AddComponents().AddStartup(startup);
        Assert.AreEqual(0, startup.A);
        Assert.AreEqual(0, startup.B);
        Assert.AreEqual(0, startup.C);
        using var host = builder.Build();
        Assert.AreEqual(1, startup.A);
        Assert.AreEqual(0, startup.B);
        Assert.AreEqual(0, startup.C);
        var task = host.RunAsync();
        Thread.Sleep(1000);
        Assert.AreEqual(1, startup.A);
        Assert.AreEqual(1, startup.B);
        Assert.AreEqual(0, startup.C);
        host.StopAsync().Wait();
        task.Wait();
        Assert.AreEqual(1, startup.A);
        Assert.AreEqual(1, startup.B);
        Assert.AreEqual(1, startup.C);
    }

    [TestMethod]
    public void Test3()
    {
        var builder = Host.CreateDefaultBuilder().AddComponents().AddStartup((object)typeof(Startup));
        using var host = builder.Build();
        var startup = host.Services.GetRequiredService<Startup>();
        Assert.AreEqual(1, startup.A);
        Assert.AreEqual(0, startup.B);
        Assert.AreEqual(0, startup.C);
        var task = host.RunAsync();
        Thread.Sleep(1000);
        Assert.AreEqual(1, startup.A);
        Assert.AreEqual(1, startup.B);
        Assert.AreEqual(0, startup.C);
        host.StopAsync().Wait();
        task.Wait();
        Assert.AreEqual(1, startup.A);
        Assert.AreEqual(1, startup.B);
        Assert.AreEqual(1, startup.C);
    }

    class Startup
    {
        public int A { get; set; }
        public int B { get; set; }
        public int C { get; set; }

        [ConfigureServices]
        public void RunA()
        {
            A++;
        }

        [Configure]
        public void RunB()
        {
            B++;
        }

        [HostStop]
        public void RunC()
        {
            C++;
        }
    }
}
